/*
 * Copyright (c) 2016-2017 fulihui.com All right reserved
 * Project: information-core-170307
 * File name: CategoryStatisticsManagerImpl.java
 */
package com.fulihui.information.biz.content.impl;

import com.fulihui.information.biz.content.CategoryStatisticsManager;
import com.fulihui.information.dal.dataobj.InfoCategory;
import com.fulihui.information.dal.dataobj.InfoCategoryStatistics;
import com.fulihui.information.dal.dataobj.InfoCategoryStatisticsExample;
import com.fulihui.information.dal.mapper.InfoCategoryMapper;
import com.fulihui.information.dal.mapper.InfoCategoryStatisticsMapper;
import com.fulihui.information.dto.CategoryStatisticsDTO;
import com.fulihui.information.enums.ECategoryStatisticsSortField;
import com.fulihui.information.request.CategoryStatisticsQueryRequest;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static java.util.Collections.emptyList;
import static org.near.toolkit.common.EnumUtil.queryByCode;
import static org.near.toolkit.common.StringUtil.isNotBlank;

/**
 * @author Willard.Hu on 2017/2/15 0015.
 */
@Component
public class CategoryStatisticsManagerImpl implements CategoryStatisticsManager {

    @Autowired
    private InfoCategoryStatisticsMapper infoCategoryStatisticsMapper;
    @Autowired
    private InfoCategoryMapper           infoCategoryMapper;

    /**
     * @see CategoryStatisticsManager#query(CategoryStatisticsQueryRequest)
     */
    @Override
    public List<CategoryStatisticsDTO> query(CategoryStatisticsQueryRequest request) {
        Multimap<String, InfoCategoryStatistics> data = queryLimitBasicData(
                request.getStartDate(), request.getEndDate());
        Set<String> keys = data.keySet();
        List<CategoryStatisticsDTO> res;
        if (keys != null) {
            res = keys.stream().map(it -> toDTO(it, data.get(it))).collect(Collectors.toList());
            if (isNotBlank(request.getSortField())) {
                sortDispatch(request.getSortField(), res);
            }
        } else {
            res = emptyList();
        }
        return res;
    }

    /**
     * 按时间区间查询数据库基础统计数据
     */
    private Multimap<String, InfoCategoryStatistics> queryLimitBasicData(String startDate, String endDate) {
        InfoCategoryStatisticsExample example = new InfoCategoryStatisticsExample();
        example.createCriteria().andDateIntervalBetween(startDate, endDate);
        List<InfoCategoryStatistics> list = infoCategoryStatisticsMapper.selectByExample(example);
        Multimap<String, InfoCategoryStatistics> data = HashMultimap.create();
        if (list != null) {
            list.forEach(it -> data.put(it.getCategoryCode(), it));
        }
        return data;
    }

    private CategoryStatisticsDTO toDTO(String categoryCode, Collection<InfoCategoryStatistics> values) {
        InfoCategory infoCategory = infoCategoryMapper.selectByPrimaryKey(categoryCode);

        CategoryStatisticsDTO record = new CategoryStatisticsDTO();
        record.setCategoryCode(categoryCode);
        record.setCategoryName(infoCategory.getName());

        long readTimes = 0, sharedTimes = 0, commentTimes = 0, starTimes = 0, voteupTimes = 0, votedownTimes = 0;
        for (InfoCategoryStatistics v : values) {
            readTimes += v.getReadTimes();
            sharedTimes += v.getSharedTimes();
            commentTimes += v.getCommentTimes();
            starTimes += v.getStarTimes();
            voteupTimes += v.getVoteupTimes();
            votedownTimes += v.getVotedownTimes();
        }
        record.setReadTimes(readTimes);
        record.setSharedTimes(sharedTimes);
        record.setCommentTimes(commentTimes);
        record.setStarTimes(starTimes);
        record.setVoteupTimes(voteupTimes);
        record.setVotedownTimes(votedownTimes);
        return record;
    }

    /**
     * 按排序字段选择比较器，并执行排序
     */
    private void sortDispatch(String sortField, List<CategoryStatisticsDTO> list) {
        ECategoryStatisticsSortField sortFieldEnum = queryByCode(sortField, ECategoryStatisticsSortField.class);
        switch (sortFieldEnum) {
            case READ_TIMES:
                list.sort(new ReadTimesComparator());
                break;
            case SHARED_TIMES:
                list.sort(new SharedTimesComparator());
                break;
            case COMMENT_TIMES:
                list.sort(new CommentComparator());
                break;
            case STAR_TIMES:
                list.sort(new StarTimesComparator());
                break;
            case VOTEUP_TIMES:
                list.sort(new VoteupTimesComparator());
                break;
            case VOTEDOWN_TIMES:
                list.sort(new VotedownTimesComparator());
                break;
            default:
                throw new IllegalArgumentException("Unsupported sortField '" + sortField + "'");
        }
    }

    /**
     * 读取次数的比较器
     */
    private class ReadTimesComparator implements Comparator<CategoryStatisticsDTO> {
        @Override
        public int compare(CategoryStatisticsDTO a, CategoryStatisticsDTO b) {
            if (a.getReadTimes() == b.getReadTimes()) {
                return 0;
            }
            return b.getReadTimes() > a.getReadTimes() ? 1 : -1;
        }
    }

    /**
     * 分享次数的比较器
     */
    private class SharedTimesComparator implements Comparator<CategoryStatisticsDTO> {
        @Override
        public int compare(CategoryStatisticsDTO a, CategoryStatisticsDTO b) {
            if (a.getSharedTimes() == b.getSharedTimes()) {
                return 0;
            }
            return b.getSharedTimes() > a.getSharedTimes() ? 1 : -1;
        }
    }

    /**
     * 评论次数比较器
     */
    private class CommentComparator implements Comparator<CategoryStatisticsDTO> {
        @Override
        public int compare(CategoryStatisticsDTO a, CategoryStatisticsDTO b) {
            if (a.getCommentTimes() == b.getCommentTimes()) {
                return 0;
            }
            return b.getCommentTimes() > a.getCommentTimes() ? 1 : -1;
        }
    }

    /**
     * 收藏次数比较器
     */
    private class StarTimesComparator implements Comparator<CategoryStatisticsDTO> {
        @Override
        public int compare(CategoryStatisticsDTO a, CategoryStatisticsDTO b) {
            if (a.getStarTimes() == b.getStarTimes()) {
                return 0;
            }
            return b.getStarTimes() > a.getStarTimes() ? 1 : -1;
        }
    }

    /**
     * 赞数量比较器
     */
    private class VoteupTimesComparator implements Comparator<CategoryStatisticsDTO> {
        @Override
        public int compare(CategoryStatisticsDTO a, CategoryStatisticsDTO b) {
            if (a.getVoteupTimes() == b.getVoteupTimes()) {
                return 0;
            }
            return b.getVoteupTimes() > a.getVoteupTimes() ? 1 : -1;
        }
    }

    /**
     * 踩数量比较器
     */
    private class VotedownTimesComparator implements Comparator<CategoryStatisticsDTO> {
        @Override
        public int compare(CategoryStatisticsDTO a, CategoryStatisticsDTO b) {
            if (a.getVotedownTimes() == b.getVotedownTimes()) {
                return 0;
            }
            return b.getVotedownTimes() > a.getVotedownTimes() ? 1 : -1;
        }
    }

}
